package org.zoomdev;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.zoomdev.zoom.lockfree.FastStringBuilder;

import java.util.*;
import java.util.concurrent.*;

@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 3, time = 1)
@Measurement(iterations = 5, time = 2)
@Fork(value = 1, jvmArgs = {"-Xms8g", "-Xmx8g", "-XX:+UseParallelGC"})
public class FastStringBuilderBenchmark {

    @State(Scope.Thread)
    public static class BuilderState {
        public StringBuilder standardBuilder;
        public FastStringBuilder fastBuilder;
        public String[] smallStrings;
        public String largeString;

        @Setup(Level.Trial)
        public void setup() {
            standardBuilder = new StringBuilder();
            fastBuilder = new FastStringBuilder();

            // 生成1000个短字符串 (5-15个字符)
            smallStrings = new String[1000];
            Random random = new Random();
            for (int i = 0; i < smallStrings.length; i++) {
                smallStrings[i] = generateRandomString(random, 5, 15);
            }

            // 生成长字符串 (10KB)
            largeString = generateRandomString(random, 10240, 10240);
        }

        private String generateRandomString(Random random, int min, int max) {
            int length = min + random.nextInt(max - min + 1);
            StringBuilder sb = new StringBuilder(length);
            for (int j = 0; j < length; j++) {
                sb.append((char)('a' + random.nextInt(26)));
            }
            return sb.toString();
        }
    }

    // 1. 基本追加操作测试
    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    public void testStandardStringBuilder(BuilderState state, Blackhole blackhole) {
        state.standardBuilder.setLength(0);
        for (String str : state.smallStrings) {
            state.standardBuilder.append(str);
        }
        blackhole.consume(state.standardBuilder.toString());
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    public void testFastStringBuilder(BuilderState state, Blackhole blackhole) {
        state.fastBuilder.reset();
        for (String str : state.smallStrings) {
            state.fastBuilder.append(str);
        }
        blackhole.consume(state.fastBuilder.build());
    }

    // 2. 大字符串构建性能
    @Benchmark
    @BenchmarkMode(Mode.SampleTime)
    public void testLargeStringStandard(BuilderState state, Blackhole blackhole) {
        state.standardBuilder.setLength(0);
        for (int i = 0; i < 100; i++) {
            state.standardBuilder.append(state.largeString);
        }
        blackhole.consume(state.standardBuilder.toString());
    }

    @Benchmark
    @BenchmarkMode(Mode.SampleTime)
    public void testLargeStringFast(BuilderState state, Blackhole blackhole) {
        state.fastBuilder.reset();
        for (int i = 0; i < 100; i++) {
            state.fastBuilder.append(state.largeString);
        }
        blackhole.consume(state.fastBuilder.build());
    }

    // 3. 内存分配效率测试
    @Benchmark
    @BenchmarkMode(Mode.SingleShotTime)
    public void testAllocationPressureStandard(BuilderState state, Blackhole blackhole) {
        for (int i = 0; i < 100000; i++) {
            StringBuilder sb = new StringBuilder();
            sb.append(state.smallStrings[i % state.smallStrings.length]);
            blackhole.consume(sb.toString());
        }
    }

    @Benchmark
    @BenchmarkMode(Mode.SingleShotTime)
    public void testAllocationPressureFast(BuilderState state, Blackhole blackhole) {
        FastStringBuilder pool = new FastStringBuilder();
        for (int i = 0; i < 100000; i++) {
            pool.reset();
            pool.append(state.smallStrings[i % state.smallStrings.length]);
            blackhole.consume(pool.build());
        }
    }

    // 4. 并发性能测试
    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @Threads(8)
    public void testConcurrentStandard(BuilderState state, Blackhole blackhole) {
        state.standardBuilder.setLength(0);
        for (int i = 0; i < 100; i++) {
            state.standardBuilder.append(state.smallStrings[i % state.smallStrings.length]);
        }
        blackhole.consume(state.standardBuilder.toString());
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @Threads(8)
    public void testConcurrentFast(BuilderState state, Blackhole blackhole) {
        state.fastBuilder.reset();
        for (int i = 0; i < 100; i++) {
            state.fastBuilder.append(state.smallStrings[i % state.smallStrings.length]);
        }
        blackhole.consume(state.fastBuilder.build());
    }

    // 5. 特殊操作性能测试
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    public void testCodePointHandlingStandard(BuilderState state, Blackhole blackhole) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0x10000; i < 0x100FF; i++) {
            sb.appendCodePoint(i);
        }
        blackhole.consume(sb.toString());
    }

    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    public void testCodePointHandlingFast(BuilderState state, Blackhole blackhole) {
        FastStringBuilder fsb = new FastStringBuilder();
        for (int i = 0x10000; i < 0x100FF; i++) {
            fsb.appendCodepoint(i);
        }
        blackhole.consume(fsb.build());
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    public void testContainsOperationStandard(BuilderState state, Blackhole blackhole) {
        StringBuilder sb = new StringBuilder();
        for (String str : state.smallStrings) {
            sb.append(str);
        }
        boolean found = sb.indexOf("testpattern") > -1;
        blackhole.consume(found);
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    public void testContainsOperationFast(BuilderState state, Blackhole blackhole) {
        FastStringBuilder fsb = new FastStringBuilder();
        for (String str : state.smallStrings) {
            fsb.append(str);
        }
        boolean found = fsb.contains("testpattern");
        blackhole.consume(found);
    }
//
//    // 6. 虚拟线程测试
//    @Benchmark
//    @BenchmarkMode(Mode.Throughput)
//    public void testVirtualThreadsStandard(Blackhole blackhole) throws InterruptedException, ExecutionException {
//        int threadCount = 1000;
//        ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
//        List<Future<String>> futures = new ArrayList<>();
//
//        for (int i = 0; i < threadCount; i++) {
//            futures.add(executor.submit(() -> {
//                StringBuilder sb = new StringBuilder();
//                for (int j = 0; j < 100; j++) {
//                    sb.append(Thread.currentThread().getName());
//                }
//                return sb.toString();
//            }));
//        }
//
//        for (Future<String> future : futures) {
//            blackhole.consume(future.get());
//        }
//
//        executor.shutdown();
//    }
//
//    @Benchmark
//    @BenchmarkMode(Mode.Throughput)
//    public void testVirtualThreadsFast(Blackhole blackhole) throws InterruptedException, ExecutionException {
//        int threadCount = 1000;
//        ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
//        List<Future<String>> futures = new ArrayList<>();
//
//        for (int i = 0; i < threadCount; i++) {
//            futures.add(executor.submit(() -> {
//                FastStringBuilder fsb = new FastStringBuilder();
//                for (int j = 0; j < 100; j++) {
//                    fsb.append(Thread.currentThread().getName());
//                }
//                return fsb.build();
//            }));
//        }
//
//        for (Future<String> future : futures) {
//            blackhole.consume(future.get());
//        }
//
//        executor.shutdown();
//    }

    // 运行所有基准测试
    public static void main(String[] args) throws Exception {
        org.openjdk.jmh.Main.main(args);
    }
}